//
//  YZBlueToothManager.swift
//  YZFetter
//
//  Created by 康凯 on 2017/7/13.
//  Copyright © 2017年 康凯. All rights reserved.
//

import Foundation
import CoreBluetooth
import RxSwift
import PKHUD

let customerServiceUUID: String = "FFF0"
let systemInfoUUID     : String = "180A"
let peripherDisConnected: String = "peripherDisConnected"

private var perStateContext = 0


class YZBlueToothManager: NSObject {

    var centralManager: CBCentralManager!
    var centerManagerState: CBManagerState!
    var peripheral: CBPeripheral?
    var charateristic: CBCharacteristic?
    
    let peripheralList = Variable<[CBPeripheral]>([])                   // 设备列表
    let serviceList        = PublishSubject<[CBService]>()              // 设备服务列表
    var characteristicList = PublishSubject<[CBCharacteristic]>()       // 特征列表
    var characteristicValue = PublishSubject<CBCharacteristic>()        // 某个特征返回的数据

    var timeOutBlock: DispatchWorkItem!
    
    let bag = DisposeBag()
    
    // 单例方法
    class var shareInstances: YZBlueToothManager {
        struct Static {
            static let instance = YZBlueToothManager()
        }
        return Static.instance
    }
    
    override init() {
        super.init()
        centralManager = CBCentralManager.init(delegate: self, queue: nil)
        timeOutBlock = DispatchWorkItem.init(block: { 
            if self.peripheral == nil {
                HUD.flash(.labeledError(title: "错误", subtitle: "连接超时"), delay: 2) 
                self.centralManager.stopScan()
            }
        })
    }
    
    // MARK:- CustomerFunc
    
    // 检查蓝牙状态
    func checkBlueState() -> Bool {
        var message: String = ""
        if let state = self.centerManagerState {
            switch state {
                case .poweredOn:
                return true
                case .poweredOff:
                message = "请开启蓝牙"
                case .unauthorized:
                message = "设备未授权"
                case .unsupported:
                message = "设备不支持"
                case .resetting:
                message = "设备在重置"
                default:
                message = "设备状态未知"
            }
            HUD.flash(.labeledError(title: "错误", subtitle: message), delay: 2)
            return false
        }
        return false
    }
    
    // 检查连接状态
    func checkConnectStatus() -> Bool {
        if self.peripheral != nil && (self.peripheral?.state == CBPeripheralState.connected || self.peripheral?.state == CBPeripheralState.connecting) {
            return true
        }
        return false
    }
    
    // 刷新蓝牙列表
    func refreshBT() {
        if checkBlueState() {
            timeOutBlock.cancel()
            self.peripheralList.value.removeAll()
            self.cancelConnect()
            self.centralManager.scanForPeripherals(withServices: nil, options: nil)
        }
    }
    
    // 断开连接
    func cancelConnect() {
        if let currentPeripheral = self.peripheral {
            self.peripheral?.removeObserver(self, forKeyPath: "state", context: &perStateContext)
            self.peripheral?.delegate = nil
            self.peripheral = nil
            self.centralManager.cancelPeripheralConnection(currentPeripheral)
        }else {
//            self.centralManager.
        }
    }
    
    // 连接到设备
    func connect(to peripheral: CBPeripheral) {
        HUD.show(.labeledProgress(title: "正在连接", subtitle: peripheral.name))
        if checkConnectStatus() {
            cancelConnect()
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 15, execute: timeOutBlock)
        centralManager.connect(peripheral, options: nil)
    }
    
    // 订阅设备的某个服务的特征
    func subscribe(for characteristics: CBCharacteristic) {
        self.peripheral?.setNotifyValue(true, for: characteristics)
    }
    
    // 读取设备的某个服务的特征内容
    func readValue(for characteristics: CBCharacteristic) {
        HUD.show(.progress)
        self.peripheral?.readValue(for: characteristics)
    }
    
    // 像某个特征发送数据
    func write(data writeData: Data, for characteristics: CBCharacteristic)  {
        self.peripheral?.writeValue(writeData, for: characteristics, type: .withResponse)
    }
}

// MARK:- CBCentralManagerDelegate
extension YZBlueToothManager: CBCentralManagerDelegate {
    // 当手机蓝牙状态改变的额时候会自动调用
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        self.centerManagerState = central.state
    }
    
    // 扫描到外设
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        
        if !peripheralList.value.contains(peripheral) , peripheral.name != nil , !(peripheral.name?.isEmpty)! {
            peripheralList.value.append(peripheral)
        }
    }
    
    // 连接成功
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        HUD.hide(animated: true)
        centralManager.stopScan()
        self.peripheral = peripheral
        self.peripheral?.addObserver(self, forKeyPath: "state", options: .new, context: &perStateContext)
        self.peripheral?.delegate = self
        
        // 扫描服务
        self.peripheral?.discoverServices(nil)
    }
    
    // 连接失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        HUD.flash(.labeledError(title: "连接失败", subtitle: error.debugDescription), delay: 0)
        centralManager.stopScan()
    }
}

// MARK:- CBPeripheralDelegate
extension YZBlueToothManager: CBPeripheralDelegate {
    // 扫描到服务
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        guard error == nil else {
            print(error.debugDescription)
            return
        }
        
        for service in peripheral.services! {
            if service.uuid == CBUUID.init(string: customerServiceUUID){
                peripheral.discoverCharacteristics(nil, for: service)
            }
            
//            if service.uuid.uuidString == systemInfoUUID {
//                peripheral.discoverCharacteristics(nil, for: service)
//            }
        }
    }
    
    // 扫描到特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        guard error == nil else {
            print(error.debugDescription)
            return
        }

        // 将特征发送出去
        characteristicList.onNext(service.characteristics!)
    }
    
    // 当设备有数据返回的时候的回调方法
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        
        HUD.hide()
        guard error == nil else {
            print(error.debugDescription)
            return
        }
        characteristicValue.onNext(characteristic)
    }
}

extension YZBlueToothManager {
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "state", context == &perStateContext {
//            HUD.flash(.labeledError(title: "错误", subtitle: "连接已断开"), delay: 2)
            if peripheral?.state == .disconnected {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: peripherDisConnected), object: nil)
            }
        }
    }
}
    

